//
// Created by hunan on 25-3-8.
//

#ifndef TCP_SOCKET_SERVER_CONNECTION_H
#define TCP_SOCKET_SERVER_CONNECTION_H

#include "socket_module/tcp_socket_connection.h"
#include "socket_server_connection.h"
#include "write_read_module/buffer.h"

#include <cstdint>
#include <memory>
#include <set>

class Loop;
class SocketDescription;
class SocketChannel;
class TcpSocketServerChannel;
class TcpSocketServerConnection;
class TcpSocketServerConnectionChannel;

class TcpSocketServer : public SocketServer,
                        public std::enable_shared_from_this<TcpSocketServer>
{
public:
    explicit TcpSocketServer(Loop * loop);
    ~TcpSocketServer() override = default;
    int BindAddress(const SocketServer::Option & option) override;
    int Listen() override;
    struct CmpConnection
    {
        bool operator()(const std::shared_ptr<SocketServerConnection> & a, const std::shared_ptr<SocketServerConnection> & b) const
        {
            return a.get() != b.get();
        }
    };
    Loop * GetLoop() const;
private:
    friend class TcpSocketServerChannel;
    Loop *                                  m_loop;
    std::shared_ptr<SocketDescription>      m_description;
    std::shared_ptr<TcpSocketServerChannel> m_channel;
    SocketServer::Option                    m_option;
    std::set<std::shared_ptr<SocketServerConnection>,CmpConnection> m_connection_set;
};

class TcpSocketServerConnection : public SocketServerConnection, public std::enable_shared_from_this<TcpSocketServerConnection>
{
public:
    explicit TcpSocketServerConnection(TcpSocketServer * server, const std::shared_ptr<Description> & description);
    int  AsyncWrite(const uint8_t * data, int data_length) override;
    int  AsyncRead() override;
    void Close() override;
    void UpdateOption(const ClientOption &option) override;
private:
    friend class TcpSocketServerConnectionChannel;
    TcpSocketServer                                 * m_server;
    std::shared_ptr<Description>                      m_description;
    std::shared_ptr<TcpSocketServerConnectionChannel> m_channel;
    SocketServerConnection::ClientOption              m_client_option{};
    WriteReadBuffer m_write_buffer;
    WriteReadBuffer m_read_buffer;
};

#endif // TCP_SOCKET_SERVER_CONNECTION_H
